
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Diagnostics;

using Swaf;
using Swaf.BizObj;

namespace Swaf.BizObj
{
	/// <summary>
	/// Field Decorator to enable a business object field to be trimmed automatically.
	/// </summary>
	[Serializable]
	public class TrimFieldDecorator : GenericDecorator, IBizObjDecorator
	{
		protected enum TrimType { None = 0, True = 1, Get = 2 }

		protected TrimType m_trimType = TrimType.None;

		public TrimFieldDecorator(string name, string val, object otherInfo)
			:base(name, val, otherInfo)
		{
			try
			{
				m_trimType = (TrimType) Enum.Parse(typeof(TrimType), m_val, true);
			}
			catch (Exception e)
			{
				throw new TrimDecoratorException(
					String.Format("Invalid value '{0}' specified for trim bizobj field decorator.  Valid values include 'get' and 'true'",
					val), e);
			}
		}

		#region IBizObjDecorator Members

		/// <summary>
		/// When the value is received one of the following will occur:
		/// 
		/// If trimType is True and the value is a string it will be trimmed.
		/// 
		/// If trimType is Get and the value is a string it will be trimmed.

		/// If trimType is anything else it will not be trimmed.
		/// </summary>
		/// <param name="parent"></param>
		/// <param name="field"></param>
		/// <param name="val"></param>
		/// <param name="extraInfo"></param>
		/// <param name="shouldBeFieldType"></param>
		public void put(IBizObj parent, IBizObjField field, ref object val, object extraInfo, ref bool shouldBeFieldType)
		{
			if (val != null && (val is string))
			{
				// Value with be a field type
				shouldBeFieldType = true;
				
				// TrimType of True means keep the value trimmed
				if ((m_trimType == TrimType.True))
				{
					val = ((string) val).Trim();
				}
			}
		}

		/// <summary>
		/// When a value is requested on of the following will occur:
		/// 
		/// If trim type is True return value as is because it is already trimmed in memory.
		/// 
		/// If trim type is Get return a trimmed version of the value.
		/// 
		/// If trim type is Get and extraInfo is notrim, return the value will not be trimmed.
		/// </summary>
		/// <param name="parent"></param>
		/// <param name="field"></param>
		/// <param name="val"></param>
		/// <param name="extraInfo"></param>
		/// <param name="shouldBeFieldType"></param>
		public void get(IBizObj parent, IBizObjField field, ref object val, object[] extraInfo, ref bool shouldBeFieldType)
		{
			if (val != null && (val is string))
			{
				// Value with be a field type
				shouldBeFieldType = true;
				
				// Get the trim directions from the extra info
				if ((m_trimType == TrimType.Get))
				{
					bool trimValue = true;

					if (extraInfo != null)
					{
						// Search extraInfo for trim directions to suppress the trim when Get is specified
						foreach (object trimDirection in extraInfo)
						{
							if (trimDirection.ToString().Equals("notrim"))
							{
								trimValue = false;
								break;
							}
						}
					}

					// Trim value if specified
					val = (trimValue) ? ((string) val).Trim() : val;
				}
			}
		}

		/// <summary>
		/// This is used by XML serialization of bizobjs to control whether the decorator consumes the
		/// entire XML element for the field (OuterXML) or just the inner xml element content
		/// (InnerXML).  When encryption is applied to a field it is always using the inner xml content
		/// </summary>
		public bool doesUseFullXmlElement()
		{
			return false;
		}
		#endregion

		/// <summary>
		/// Indicates that this decorator manipulates the field value for the bizobj.  
		/// This decorator is always a stand-in.
		/// </summary>
		public override bool IsStandin { get { return true; } }
	}

	/// <summary>
	/// Exception class to handle valid values for trimming biz objects
	/// </summary>
	public class TrimDecoratorException : BaseException
	{
		/// <summary>
		/// Default Constructor
		/// </summary>
		public TrimDecoratorException() 
			: base()
		{
		}

		/// <summary>
		/// Serialization constructor
		/// </summary>
		/// <param name="info"></param>
		/// <param name="context"></param>
		public TrimDecoratorException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) 
			: base(info, context)
		{
		}	

		/// <summary>
		/// Standard message string constructor
		/// </summary>
		/// <param name="message"></param>
		public TrimDecoratorException(string message)
			: base(message)
		{
			
		}	

		/// <summary>
		/// Message string constructor with inner exception
		/// </summary>
		/// <param name="message"></param>
		/// <param name="innerException"></param>
		public TrimDecoratorException(string message, Exception innerException)
			: base(message, innerException)
		{	
		}	
	}
}
